package com.lims.exception;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import com.lims.common.BaseResult;
import com.lims.common.ResultCode;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.util.ContentCachingRequestWrapper;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {


    @ExceptionHandler(BaseException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public BaseResult baseException(HttpServletRequest request, BaseException e) {
        return log(request, e.getCode(), e.getMessage(), null);
    }


    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public BaseResult methodArgumentNotValidExceptionExceptionHandler(HttpServletRequest request, MethodArgumentNotValidException ex) {
        List<String> list = new ArrayList<>();
        String message = "";
        try {
            ex.getBindingResult().getAllErrors().forEach((error) -> {
                String fieldName = ((FieldError) error).getField();
                String errorMessage = error.getDefaultMessage();
                list.add(errorMessage + "(" + fieldName + ")");
            });
            message = String.join(",", list);
        } catch (Exception e) {
        }
        return log(request, ResultCode.PARAM_ERROR.getCode(), message, null);
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public BaseResult defaultExceptionHandler(HttpServletRequest request, Throwable ex) {
        return log(request, ResultCode.INTERNAL_SERVER_ERROR.getCode(), ResultCode.INTERNAL_SERVER_ERROR.getMsg(), ex);
    }

    private String getRequestBody(HttpServletRequest request) {
        String requestBody = "";
        try {
            if (request instanceof ContentCachingRequestWrapper) {
                ContentCachingRequestWrapper wrappedRequest = (ContentCachingRequestWrapper) request;
                byte[] contentAsByteArray = wrappedRequest.getContentAsByteArray();
                if (contentAsByteArray.length != 0) {
                    requestBody = new String(contentAsByteArray, StandardCharsets.UTF_8);
                }
            }
        } catch (Exception e) {
        }
        return requestBody;
    }

    private BaseResult log(HttpServletRequest request, Integer code, String msg, Throwable ex) {
        String contentType = request.getContentType();
        if (null == contentType) {
            contentType = request.getHeader("content-type");
        }
        if (StrUtil.isNotBlank(contentType) && contentType.contains(ContentType.JSON.getValue())) {
            log.error("[GlobalExceptionHandler]请求url:{},错误码:{},错误信息:{},请求参数:{}", request.getRequestURI(), code, msg, this.getRequestBody(request), ex);
        } else {
            log.error("[GlobalExceptionHandler]请求url:{},错误码:{},错误信息:{}", request.getRequestURI(), code, msg, ex);
        }
        return BaseResult.failed(code, msg);
    }
}
